package com.udima.reglocation;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.udima.reglocation.util.LogHelper;

/**
 * Actividad de obtención y registro de datos de localización geográfica del
 * dispositivo. El cliente obtienen mediante el dispositivo GPS del teléfono los
 * datos que permiten identificar la ruta seguida durante un periodo de tiempo y
 * los envia de manera periódica al servidor para que sean registrados.
 * 
 * @author luis
 * 
 */

public class SaveTrackActivity extends Activity {

	private Button btnStart;
	private Button btnStop;
	private TextView messageTextView;
	private TextView locationTextView;
	private TextView periodTextView;
	private ImageView imgGpsStatus;

	private LocationServiceReceiver locReceiver;

	@Override
	/**
	 * Método que se ejecuta tras la creación de la actividad
	 *    
	 * En la creación de la clase se instancian los objetos del control y se
	 * crean las funciones de escucha para los botones
	 *    
	 * @param savedInstanceState Contiene la información previa de la actividad en caso de que se vuelva a recrear
	 */
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		setContentView(R.layout.save_track_activity);

		// registramos los receptores de anuncios para comunicarnos con el
		// servicio de captura de datos
		locReceiver = new LocationServiceReceiver();

		IntentFilter locationServiceStatusFilter = new IntentFilter(LocationService.ACTION_LOCATION_SERVICE_COORDS);
		locationServiceStatusFilter.addCategory(Intent.CATEGORY_DEFAULT);
		registerReceiver(locReceiver, locationServiceStatusFilter);

		IntentFilter sendDataPeriodServiceStatusFilter = new IntentFilter(LocationService.ACTION_LOCATION_SERVICE_SENDDATAPERIOD);
		sendDataPeriodServiceStatusFilter.addCategory(Intent.CATEGORY_DEFAULT);
		registerReceiver(locReceiver, sendDataPeriodServiceStatusFilter);

		IntentFilter geolocationDisabledServiceStatusFilter = new IntentFilter(LocationService.ACTION_LOCATION_SERVICE_GEOLOCATIONDISABLED);
		sendDataPeriodServiceStatusFilter.addCategory(Intent.CATEGORY_DEFAULT);
		registerReceiver(locReceiver, geolocationDisabledServiceStatusFilter);

		// Texto e imagen de estado del GPS
		messageTextView = (TextView) findViewById(R.id.gps_status);
		locationTextView = (TextView) findViewById(R.id.location);
		periodTextView = (TextView) findViewById(R.id.fetchGpsLapseTime);
		imgGpsStatus = (ImageView) findViewById(R.id.imgGpsStatus);

		// Botones
		btnStart = (Button) findViewById(R.id.btnStart);
		btnStop = (Button) findViewById(R.id.btnStop);

		updateStatusServiceOnScreen();

		// listener para el boton de arranque del servicio
		// se arranca el servicio LocationService
		btnStart.setOnClickListener(new OnClickListener() {

			public void onClick(View view) {
				// arrancamos el servicio de envio de datos
				startService(new Intent(SaveTrackActivity.this, LocationService.class));
				updateStatusServiceOnScreen();
			}

		});

		// listener para el boton de parada del servicio
		// se detiene el servicio LocationService
		btnStop.setOnClickListener(new View.OnClickListener() {

			public void onClick(View view) {
				// paramos el servicio de envio de datos
				stopService(new Intent(SaveTrackActivity.this, LocationService.class));
				updateStatusServiceOnScreen();
			}

		});
	}

	@Override
	/**
	 * 
	 * Destructor de la clase
	 * 
	 */
	public void onDestroy() {
		super.onDestroy();
		unregisterReceiver(locReceiver);
	}

	/**
	 * 
	 * Actualización de la información de la pantalla tras la lectura de datos del GPS
	 * 
	 */
	private void updateStatusServiceOnScreen() {
		// Cambio el mensaje, la imagen de estado del servicio y el estado del
		// boton de arranque/parada de servicio
		if (isLocationServiceRunning()) {
			messageTextView.setText(R.string.service_status_started);
			imgGpsStatus.setImageResource(getResources().getIdentifier("gps_receiving", "drawable", getPackageName()));
			btnStart.setVisibility(Button.GONE);
			btnStop.setVisibility(Button.VISIBLE);
			periodTextView.setText("");
			periodTextView.setVisibility(TextView.VISIBLE);
			locationTextView.setText("");
			locationTextView.setVisibility(TextView.VISIBLE);
		} else {
			messageTextView.setText(R.string.service_status_stopped);
			imgGpsStatus.setImageResource(getResources().getIdentifier("gps_disconnected", "drawable", getPackageName()));
			btnStart.setVisibility(Button.VISIBLE);
			btnStop.setVisibility(Button.GONE);
			periodTextView.setText("");
			periodTextView.setVisibility(TextView.GONE);
			locationTextView.setText("");
			locationTextView.setVisibility(TextView.GONE);
		}

	}

	/**
	 * Pregunta si el servicio de localización está ejecutándose
	 * 
	 * @return boolean Valor booleano que indica si el servicio se ejecuta o no
	 */
	private boolean isLocationServiceRunning() {
		ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
		for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
			if (LocationService.class.getName().equals(service.service.getClassName())) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Receptor del estado del servicio LocationService
	 * 
	 * @author david
	 */
	private class LocationServiceReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().equals(LocationService.ACTION_LOCATION_SERVICE_SENDDATAPERIOD)) {
				int period = intent.getIntExtra("sendDataPeriod", 0);
				periodTextView.setText("Envío de datos de posición cada " + (period / 1000) + " segundos");
			} else if (intent.getAction().equals(LocationService.ACTION_LOCATION_SERVICE_GEOLOCATIONDISABLED)) {
				showSettingsAlert();
				updateStatusServiceOnScreen();
			} else if (intent.getAction().equals(LocationService.ACTION_LOCATION_SERVICE_COORDS)) {
				double lat = intent.getDoubleExtra("lat", 0);
				double lon = intent.getDoubleExtra("lon", 0);
				locationTextView.setText("Recibiendo datos\n lat: " + String.valueOf(lat) + "\n lon: " + String.valueOf(lon));
			} else if (intent.getAction().equals(LocationService.ACTION_LOCATION_SERVICE_USERSESSIONNOTPRESENT)) {
				// No hay sesión. Se redirige al usuario a la ventana de login
				Intent i = new Intent(getBaseContext(), LoginActivity.class);
				startActivity(i);
			} else if (intent.getAction().equals(LocationService.ACTION_LOCATION_SERVICE_CONNECTIONERROR)) {
				Toast.makeText(getBaseContext(), "Error conectando con el servidor", Toast.LENGTH_LONG).show();
			} else if (intent.getAction().equals(LocationService.ACTION_LOCATION_SERVICE_NONRECOVERABLEERROR)) {
				Toast.makeText(getBaseContext(), "Error grave!! Revise el log de la aplicación", Toast.LENGTH_LONG).show();
				LogHelper.logError("Error non recoverable in LocationService: " + intent.getStringExtra("exception"));
			}
		}
	}

	/**
	 * Función que muestra la ventana de alerta de configuración del GPS Al
	 * pulsar el botón de configuración se redirige al usuario a la pantalla de
	 * configuración
	 */
	private void showSettingsAlert() {
		AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);

		// Título de la alerta
		alertDialog.setTitle(R.string.alert_gpstracker_title);

		// Mensaje de la alerta
		alertDialog.setMessage(R.string.alert_gpstracker_message);

		// Acción tras pulsar el botón de configuración
		alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
				SaveTrackActivity.this.startActivity(intent);
			}
		});

		// Acción tras pulsar el botón de cancelar
		alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				dialog.cancel();
			}
		});

		// Se muestra el mensaje de alerta
		alertDialog.show();
	}

}
